package com.yukefms.engine.running;

import com.yukefms.common.Counter;
import com.yukefms.common.Timer;
import com.yukefms.jointpoint.BodyPointCloud;
import com.yukefms.jointpoint.interfaces.Position;
import com.yukefms.rule.interfaces.BARule;
import com.yukefms.rule.state.RuleStateFlyWeight;

import java.util.List;

/**
 * @Description
 * @Author Ping
 * @Date 2021/6/16 0:51
 **/
public interface RunningContext extends InputErrorAwareness,
                       TimeoutAwareness, TrialoutEventAwareness
                        , SuccessAwareness, FailedAwareness
                        , DefaultEventAwareness {


    /**
     * relevant jointTypes for rule
     * @return
     */
    List<String> relevantJointTypes() ;

    /**
     * body id which is currently processed by FMS engine.
     * @return
     */
    String bodyId() ;

    /**
     * set body id
     * @param bId
     */
    void setBodyId(String bId) ;

    /**
     * get involved rule
     * @return
     */
    BARule getInvolvedRule() ;

    /**
     * set current accessed involved rule.
     * @param involvedRule
     */
    void setInvolvedRule(BARule involvedRule) ;
    /**
     * reset timer
     */
    void resetTimer() ;
    /**
     * reset counter
     */
    void resetInputErrorCounter() ;
    /**
     * reset counter
     */
    void resetTrialoutCounter() ;

    void resetInvariantFailCounter() ;

    void resetPerformingFailCounter() ;


   Timer getTimeoutTimer() ;

   Counter getInputErrorCounter() ;

   Counter getTrialoutCounter() ;

   Counter getInvariantFailCounter() ;
   Counter getPerformingFailCounter() ;
   default void updateTimer() {
       getTimeoutTimer().update();
   }

   default void updateInputErrorCounter() {
       getInputErrorCounter().update();
   }
   default void updateTrialoutCounter() {
       getTrialoutCounter().update() ;
   }
   default void updateInvariantFailCounter() {
       getInvariantFailCounter().update();
   }
   default void updatePerformingFailCounter() {getPerformingFailCounter().update();}


    /**
     * get the current evaluated constraint
     * @return cid, the constraint is being evaluated.
     */
    String ruleName() ;


    /**
     * whether the maximal action time （cf {@code EngineConfig.INTERVAL_MS}）was arrived.
     * @return
     */
    boolean isTimeout() ;

    /**
     * whether the maximal trial time （cf {@code EngineConfig.TRIAL_TIME}）was arrived.
     * @return
     */
    boolean isTrialout() ;

    /**
     * whether the max tolerant input error time （cf {@code EngineConfig.TOLERANT_INPUT_ERROR}） was arrived
     * @return
     */
    boolean isInputError() ;

    /**
     * the input {@code pointCloud} for related joint types are tracked.
     * @param pointCloud
     * @return
     */
    default boolean areAllRelevant(BodyPointCloud pointCloud) {
        return pointCloud.allRelevant(relevantJointTypes()) ;
    }

    /**
     * get last position at current time for given jointType, wherein, the gotten last position was applied to access
     * dynamic formula.
     * @param jointType
     * @return
     */
    Position getLastPosition(String jointType) ;
    boolean hasCachedLastPosition() ;
    Position getStartPosition(String jointType) ;

    /**
     * updating caching pointcloud to the caching structure.
     */
    void updateCachingPointCloud(BodyPointCloud pointCloud) ;

    /**
     * resetting/clear caching structure for next round. It is important for the dynamic action,
     * which is evaluated by previous pointCloud.
     */
    void resetCachingStructure() ;

    /**
     * caching the trggering starting point cloud
     * @param pointCloud
     */
    void cacheTriggerStartPointCloud(BodyPointCloud pointCloud) ;
    /**
     * check if the rule was finished for its accessing.
     * @return
     */
    default boolean ruleIsFinished() {
        return getInvolvedRule().getRuleState() == RuleStateFlyWeight.getState(RuleStateFlyWeight.SUCCESS)
                ||
                getInvolvedRule().getRuleState() == RuleStateFlyWeight.getState(RuleStateFlyWeight.FAILED) ;

    }

    /**
     * update action score
     * @param score
     */
    public void updateScore(double score) ;

    /**
     * get current score.
     * @return
     */
    public double currentScore() ;




}
